package com.zhongli.devplatform.service.impl.sys;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zhongli.devplatform.service.imp.sys.ReadSendSmsService;
import com.zhongli.devplatform.service.imp.sys.ReadSystemParameterService;
import lombok.extern.slf4j.Slf4j;


import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.text.SimpleDateFormat;
import java.util.*;

@Service("huaweiSendSmsService")
@Slf4j
public class HuaweiSendSmsServiceImpl implements ReadSendSmsService {

    //无需修改,用于格式化鉴权头域,给"X-WSSE"参数赋值
    private static final String WSSE_HEADER_FORMAT = "UsernameToken Username=\"%s\",PasswordDigest=\"%s\",Nonce=\"%s\",Created=\"%s\"";
    //无需修改,用于格式化鉴权头域,给"Authorization"参数赋值
    private static final String AUTH_HEADER_VALUE = "WSSE realm=\"SDP\",profile=\"UsernameToken\",type=\"Appkey\"";

    @Autowired
    private RestTemplate restTemplate;


    @Autowired
    private ReadSystemParameterService systemParameterService;

    //必填,请参考"开发准备"获取如下数据,替换为实际值
    String url = null;
    String appKey = null;
    String appSecret = null;
    String sender = null;
    String signature = null;


    private void initParameter() {
        //必填,请参考"开发准备"获取如下数据,替换为实际值
        url = systemParameterService.getSystemParameter("huawei_sms_url"); //APP接入地址+接口访问URI
        appKey = systemParameterService.getSystemParameter("huawei_sms_app_key"); //APP_Key
        appSecret = systemParameterService.getSystemParameter("huawei_sms_app_secret"); //APP_Secret
        sender = systemParameterService.getSystemParameter("huawei_sms_sender"); //国内短信签名通道号或国际/港澳台短信通道号
        signature = systemParameterService.getSystemParameter("huawei_sms_signature");

    }


    @Override
    @Async
    public void send(String templateKey, List<String> receivers, String... templateParas) throws Exception {
        initParameter();
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add("Content-Type", "application/x-www-form-urlencoded");
        httpHeaders.add("Authorization", AUTH_HEADER_VALUE);
        httpHeaders.add("X-WSSE", buildWsseHeader());
        MultiValueMap<String, Object> paramMap = buildPostBody(templateKey, receivers, templateParas);
        HttpEntity<MultiValueMap<String, Object>> entity = new HttpEntity<>(paramMap, httpHeaders);
        restTemplate.postForEntity(url + "/sms/batchSendSms/v1", entity, JSONObject.class);

    }

    @Override
    public void send(String templateKey, String receiver, String... templateParas) throws Exception {
        send(templateKey, Arrays.asList(receiver), templateParas);
    }

    @Override
    @Async
    public void send(String templateKey, Map<String, String[]> receivers) throws Exception {

        initParameter();

        HttpHeaders httpHeaders = buildHttpHeaders();

        String postBody = buildPostBody(templateKey, receivers);
        HttpEntity<String> entity = new HttpEntity<>(postBody, httpHeaders);
        restTemplate.postForEntity(url + "/sms/batchSendDiffSms/v1", entity, JSONObject.class);


    }

    private HttpHeaders buildHttpHeaders() {

        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add("Content-Type", "application/json");
        httpHeaders.add("Authorization", AUTH_HEADER_VALUE);
        httpHeaders.add("X-WSSE", buildWsseHeader());
        return httpHeaders;
    }


    private String buildPostBody(String templateKey, Map<String, String[]> receivers) {

        Map<String, Object> bodyMap = new HashMap<>();
        bodyMap.put("from", sender);

        String templateId = systemParameterService.getSystemParameter(templateKey);

        List<Map<String, Object>> smsContents = new ArrayList();
        for (String receiver : receivers.keySet()) {
            Map<String, Object> smsContent = new HashMap();
            smsContent.put("to", Arrays.asList(receiver));
            smsContent.put("to", Arrays.asList(receiver));
            smsContent.put("templateId", templateId);
            smsContent.put("templateParas", receivers.get(receiver));
            smsContent.put("signature", signature);
            smsContents.add(smsContent);
        }

        bodyMap.put("smsContent", smsContents);
        return JSON.toJSONString(bodyMap);
    }

    private MultiValueMap<String, Object> buildPostBody(String templateKey, List<String> receivers, String... templateParas) {

        MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<String, Object>();
        paramMap.add("from", sender);
        paramMap.add("to", String.join(",", receivers));
        paramMap.add("templateId", systemParameterService.getSystemParameter(templateKey));
        paramMap.add("templateParas", JSON.toJSONString(templateParas));
        paramMap.add("signature", signature);
        return paramMap;
    }


    /**
     * 构造X-WSSE参数值
     *
     * @return
     */
    private String buildWsseHeader() {
        if (null == appKey || null == appSecret || appKey.isEmpty() || appSecret.isEmpty()) {
            System.out.println("buildWsseHeader(): appKey or appSecret is null.");
            return null;
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
        String time = sdf.format(new Date()); //Created
        String nonce = UUID.randomUUID().toString().replace("-", ""); //Nonce

        byte[] passwordDigest = DigestUtils.sha256(nonce + time + appSecret);
        String hexDigest = Hex.encodeHexString(passwordDigest);

        //如果JDK版本是1.8,请加载原生Base64类,并使用如下代码
        String passwordDigestBase64Str = Base64.getEncoder().encodeToString(hexDigest.getBytes()); //PasswordDigest

        return String.format(WSSE_HEADER_FORMAT, appKey, passwordDigestBase64Str, nonce, time);
    }


}
